import { CardItem } from "../canvas-photo/types.js";
import { getFollowingPageData2, getImageUrl, sleep} from "../../utils/canvasUtils.js";
import fs from "fs";
import path from "path";
import pLimit from "p-limit";
import cliProgress from "cli-progress";
import { axiosInstance as axios, fileUtils } from "./axios.js";
import puppeteer from "puppeteer-core"; //无头浏览器，
interface img {
    url: string;
    token: string;
}
let continueScrolling = true;
let continueRequesting = true;
const config = fileUtils.config;
const lastPageMap:any = config.lastPageMap;
let i = 1
let count =  0;


//手动更改的三项
const chromePath = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
const url = 'https://www.canva.cn/photos/search/%E4%BA%BA%E7%89%A9/';
const tip = 'people'



main();

async function main() {
  
  const browser = await puppeteer.launch({
      executablePath: chromePath,
      headless: false
  });
  const page = await browser.newPage();
  
  await page.goto(url);
  // 假设我们等待登录，停止一到两分钟
  sleep(100,60000);
  
  console.log(`现在下载的是${tip}类型图片`);
  await scrool(page)
}

//==================== 【1】滚动页面 =====================
// 一般滚动函数
const scrollPage = async (page:any) => {
  while (true) {
    await sleep(10,2000);
    await page.evaluate(() => {
      const scrollDistance = 800;
      window.scrollTo(0, window.scrollY + scrollDistance);
    });
  }
};
//快速定位滚动,用来寻找上次停止的位置
const fastscroll = async (page: any, scrollToCount: number) => {
  let fastCount = 0; // 使用专门的变量进行快速滚动过程中计数
  while (true) {
    await sleep(20, 60);
    if (fastCount >= scrollToCount) {
      break;
    }
    await page.evaluate(() => {
      const scrollDistance = 100; // 固定或按需调整
      window.scrollTo(0, window.scrollY + scrollDistance);
    });
    fastCount++;
  }
  return fastCount
};

// 封装滚动监听处理函数
const scrool = async (page:any) => {
  const lastPageCount = (lastPageMap[tip]?.count || 0) * 10;
  // 添加响应监听器
  page.on('response', async (response: any) => { 
    if (continueRequesting) {
      await tokensHandler(response);
    }
  });

  if (lastPageMap[tip].count > count) {
    continueRequesting = false;
    const fastCount = await fastscroll(page, lastPageCount);
    count = fastCount/10
    sleep(100,2000)
    console.log(`已经快速滚动到上次停止的位置，继续普通滚动。`);
    continueRequesting = true;
    await scrollPage(page);
  } else {
    console.log(`已经下载过0张${tip}图片，从头开始下载.`);
    await scrollPage(page);
  }
}

//==================== 【2】处理token ===================
// 处理拿到的token,转化为url,下载图片等等，每一轮下载一次
async function tokensHandler(response: any) {
  if (response.url().includes('masonry')) {
    continueScrolling = false;
    const { urlList, continuationToken } = await getFollowingPageData2(response.url());
    const imgUrlList: img[] = await getAllImageUrl(urlList) as img[];
    console.log("获取到一批图片url，准备下载图片.");
    lastTokenHandle(tip, continuationToken,i++)
    // 下载图片
    downloadImgs("test", imgUrlList)
    continueScrolling = true;
  }
}

async function getAllImageUrl(tokens: CardItem[]) {
    let index = 0;
  
    let data: any[] = [];
    while (index < tokens.length) {
      try {
        const res = await getImageUrl(tokens[index].token);
        data = data.concat(res);
        index++;
        if (index === tokens.length) {
          const urlList: img[] = data.map(item => ({
            url: item.url,
            token: item.token
          }));
          return urlList;
        }
      } catch (err) {
        console.log(err, "重试下载");
        await new Promise((resolve) => setTimeout(resolve, 10000));
      }
    }
}

// ===================== 【3】下载图片到本地 =====================
//纯函数： 下载图片，并重试三次
async function downloadImgWithRetry(
    imgUrl: string,
    filePath: string,
    retries = 3
  ) {
    // 如果文件已经存在，则直接返回
    if (fs.existsSync(filePath)) {
      return;
    }
    try {
      const res = await axios.get(imgUrl, {
        responseType: "arraybuffer",
      });
      fs.writeFileSync(filePath, Buffer.from(res.data));
    } catch (error) {
      if (retries > 0) {
        console.log(`⚠️ 图片下载失败，重试中...`);
        sleep(1000,1000);
        return downloadImgWithRetry(imgUrl, filePath, retries - 1);
      } else {
        fileUtils.logError(error);
      }
    }
}

//图片下载函数的封装
async function downloadImgs(keyword: string,  imgUrls: img[]) {
console.log(`🔥 开始下载 ${imgUrls.length} 张图片`);
const dir = path.resolve(fileUtils.outDirPath, keyword);
fs.mkdirSync(dir, { recursive: true }); //确保目录存在
const limit = pLimit(fileUtils.config.concurrency); // 限制下载并发

// 初始化进度条
const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.rect);
progressBar.start(imgUrls.length, 0);

const promises = imgUrls.map(async (imgUrl) => {
    //文件名处理
    const filePath = await fileNameHandle(imgUrl.token,dir);
    
    return limit(async () => {
    await downloadImgWithRetry(imgUrl.url, filePath);
    progressBar.increment(); // 更新进度条
    });
});

await Promise.all(promises);
progressBar.stop(); // 停止进度条
}

// ===================== 【4】文件名处理 =======================
//文件名处理函数
const fileNameHandle = async(imgUrl:string,dir:string):Promise<string> =>{
    const fileName = `${imgUrl}.jpg`; 
    const filePath = `${dir}/${fileName}`;
    return filePath;
}

//====================【5】参数处理===========================
//下载参数处理函数
const lastTokenHandle = async (path: string, token: string,index:number) => {
  const currentConfig: any = fileUtils.config;

  if (!currentConfig.lastTokenMap) {
    currentConfig.lastTokenMap = {};
  }
  if (!currentConfig.lastPageMap) {
    currentConfig.lastPageMap = {};
  }
  currentConfig.lastPageMap[path].page = index;
  currentConfig.lastTokenMap[path] = token;
  fileUtils.writeConfig(currentConfig);
}

const lastCountHandle = async (path: string, currentCount: number) => {
  const currentConfig: any = fileUtils.config;
  currentConfig.lastPageMap[path].count = currentCount;
  fileUtils.writeConfig(currentConfig);
}



